#include "rgb_spi_drv.h"
#include "sys_param.h"
#include "my_gpio.h"


#define SPI_MASTER                SPI1
#define SPI_MASTER_CLK            RCC_APB2_PERIPH_SPI1
#define SPI_MASTER_GPIO           GPIOB     // 新硬件版本改为PB3

#define SPI_MASTER_GPIO_CLK       RCC_APB2_PERIPH_GPIOA
#define SPI_MASTER_PIN_NSS        GPIO_PIN_4
#define SPI_MASTER_PIN_SCK        GPIO_PIN_5
#define SPI_MASTER_PIN_MISO       GPIO_PIN_6
#define SPI_MASTER_PIN_MOSI       GPIO_PIN_3    // 新硬件版本改为PB3

#define SPI_MASTER_Rx_DMA_Channel DMA_CH3
#define SPI_MASTER_Rx_DMA_FLAG    DMA_FLAG_TC3
#define SPI_MASTER_Tx_DMA_Channel DMA_CH4
#define SPI_MASTER_Tx_DMA_FLAG    DMA_FLAG_TC4


#define SPI_SLAVE_Rx_DMA_Channel DMA_CH1
#define SPI_SLAVE_Rx_DMA_FLAG    DMA_FLAG_TC1
#define SPI_SLAVE_Tx_DMA_Channel DMA_CH2
#define SPI_SLAVE_Tx_DMA_FLAG    DMA_FLAG_TC2

#define SPI_SLAVE_DR_Base           SPI2_BASE+0x0c //0x40013C0C
#define SPI_MASTER_DR_Base          SPI1_BASE+0x0c //0x4001300C

#define FIRST_LED_OFF           (0)
#define FIRST_LED_ON            (1)



typedef struct 
{
    uint8_t refresh_cnt;
    uint8_t flicker_flag;
    uint8_t disp_mode;
    uint8_t disp_sta;
    uint8_t disp_level;
    uint8_t disp_color;

    /* data */
}RGB_DISPLAY_PARAM_t;

RGB_DISPLAY_PARAM_t rgb_data = {0};

/*

用户可以选择 DMA 进行 SPI 数据传输，应用程序可以得到释放，系统效率可以大大提升。
当发送缓存 DMA 使能（SPI_CTRL2.TDMAEN 位置 1），每次 SPI_STS.TE 标志位置 1，会产生 DMA 请
求，DMA 自动将数据写入 SPI_DAT 寄存器，这将会清除 TE 标志位。当接收缓存 DMA 使能
（SPI_CTRL2.RDMAEN 位置 1），每次 SPI_STS.RNE 标志位置 1，会产生 DMA 请求，DMA 自动读取
SPI_DAT 寄存器，这将会清除 SPI_STS.RNE 标志位。
当 SPI 仅用于数据发送，仅需要使能 SPI 的发送 DMA 通道（SPI_CTRL2.TDMAEN 位置 1）。
当 SPI 仅用于数据接收，仅需要使能 SPI 的接收 DMA 通道（SPI_CTRL2.RDMAEN 位置 1）。
*/
/**************************************
 * ws2812 驱动逻辑电平: 先高电平，后低电平
 * 
 * 0码： H(200ns~380ns)+L(580ns ~1us)
 * 1码： H(580ns~1us) +L(580ns~1us)
 * 
 * 
*******************************************/
 void ws2812_logic_high(void)
{
   SPI_MASTER_GPIO->PBSC = SPI_MASTER_PIN_MOSI;
}

static void ws2812_logic_low(void)
{
    SPI_MASTER_GPIO->PBC = SPI_MASTER_PIN_MOSI;
}


__inline void spi_delay(int delay_cnt)
{
    int i;
    for(i = 0; i < delay_cnt; i ++){
        __NOP();
    }
}


__inline void black_color(void)
{
    int i;
    //  --黑色
    for(i = 0; i < 24 ; i++){
        ws2812_logic_high();
        __NOP();
        __NOP();
        __NOP();
        ws2812_logic_low();
        spi_delay(5);
    }
}

__inline void white_color(void)
{
    int i;
    //  --白色
    for(i = 0; i < 24 ; i++){
        ws2812_logic_high();
        spi_delay(5);
        ws2812_logic_low();
        spi_delay(5);
    }
}

__inline void red_color(void)
{
    int i;
// --红色
    for(i = 0; i < 8; i++){
        ws2812_logic_high();
        __NOP();
        __NOP();
        __NOP();
        ws2812_logic_low();
        spi_delay(5);
    }
    for(i = 8; i < 16; i++){
        ws2812_logic_high();
        spi_delay(5);
        ws2812_logic_low();
        spi_delay(5);
    }
   for(i = 16; i < 24; i++){
        ws2812_logic_high();
        __NOP();
        __NOP();
        __NOP();
        ws2812_logic_low();
        spi_delay(5);
    }
}

__inline void green_color(void)
{
    int i;
// --绿色
    for(i = 0; i < 8; i++){
        ws2812_logic_high();
        spi_delay(5);
        ws2812_logic_low();
        spi_delay(5);
    }
    for(i = 8; i < 24; i++){
        ws2812_logic_high();
        __NOP();
        __NOP();
        __NOP();
        ws2812_logic_low();
        spi_delay(5);
    }

}

__inline void blue_color(void)
{
    int i;
// --蓝色
    for(i = 0; i < 16; i++){
        ws2812_logic_high();
        __NOP();
        __NOP();
        __NOP();
        ws2812_logic_low();
        spi_delay(5);
    }
    for(i = 16; i < 24; i++){
        ws2812_logic_high();
        spi_delay(5);
        ws2812_logic_low();
        spi_delay(5);
    }
}

__inline void purple_color(void)
{
    int i;
// --紫色

    for(i = 0; i < 8; i++){
        ws2812_logic_high();
        __NOP();
        __NOP();
        __NOP();
        ws2812_logic_low();
        spi_delay(5);
    }

    for(i = 8; i < 16; i++){
        ws2812_logic_high();
        spi_delay(5);
        ws2812_logic_low();
        spi_delay(5);
    }

    for(i = 16; i < 24; i++){
        ws2812_logic_high();
        spi_delay(5);
        ws2812_logic_low();
        spi_delay(5);
    }
}

__inline void cur_led_on(void)
{
    switch(get_sys_rgb_color()){
        case BLACK_COLOR:{
            black_color();
            break;
        }
        case WHITE_COLOR:{
            white_color();
           break; 
        }
        case RED_COLOR:{
            red_color();
           break; 
        }
        case GREEN_COLOR:{
            green_color();
           break; 
        }
        case BLUE_COLOR:{
            blue_color();
           break; 
        }
        default:{
            purple_color();
           break; 
        }
    }
}

__inline void cur_led_off(void)
{
   int i;

    for(i = 0; i < 24 ; i++){
        ws2812_logic_high();
        __NOP();
        __NOP();
        __NOP();
        ws2812_logic_low();
        spi_delay(5);
    }
}


/********************************
 * 主机——档位灯：
 * 正常模式下的显示
*******************************/
void level_leds_display(uint8_t first_led_on_flag, uint8_t level)
{

    //rgb_index1, 状态指示灯（常亮）
    if(first_led_on_flag){
        cur_led_on();
    }
    else{
        cur_led_off();
    }
    

    //rgb_index2, （档位1,2）------5颗档位灯
    if(level > LEVEL_0){
        cur_led_on();
    }
    else{
        cur_led_off();
    }
    //rgb_index3, （档位3,4）
    if(level > LEVEL_2){
        cur_led_on();
    }
    else{
        cur_led_off();
    }
    //  rgb_index4, （档位5,6）
    if(level > LEVEL_4){
        cur_led_on();
    }
    else{
        cur_led_off();
    }
    // rgb_index5, （档位7,8）
   if(level > LEVEL_6){
        cur_led_on();
    }
    else{
        cur_led_off();
    }
    // rgb_index6, （档位9,10）
   if(level > LEVEL_8){
        cur_led_on();
    }
    else{
        cur_led_off();
    }
}

/********************************
 * 主机——模式灯：
 * // --------------模式灯
//  *  rgb_index7,rgb_index8, （模式1）
//  *  rgb_index9,rgb_index10, （模式2）
//  *  rgb_index11,rgb_index12, （模式3）
//  *  rgb_index13,rgb_index14, （模式4）
 * 正常模式下的显示
*******************************/
void mode_leds_display(void)
{
    WORK_MODE_e state;

    state = get_sys_mode();
    switch(state){
        case FACE_MODE:{
            cur_led_on();  cur_led_on();
            cur_led_off(); cur_led_off();
            cur_led_off(); cur_led_off(); 
            cur_led_off(); cur_led_off();
            break;
        }
        case BODY_MODE:{
            cur_led_off(); cur_led_off();
            cur_led_on();  cur_led_on();
            cur_led_off(); cur_led_off();
            cur_led_off(); cur_led_off();
            break;
        }
        case HAIR_MODE:{
            cur_led_off();  cur_led_off();
            cur_led_off(); cur_led_off();
            cur_led_on(); cur_led_on();
            cur_led_off(); cur_led_off();
            break;
        }
        case MAX_MODE:{ 
            cur_led_off(); cur_led_off();
            cur_led_off(); cur_led_off(); 
            cur_led_off(); cur_led_off();
            cur_led_on(); cur_led_on();
            break;
        }
        // 老化测试模式----只输出ems
        case TEST_ONLY_EMS_MODE:{
            cur_led_on(); cur_led_on();
            cur_led_on(); cur_led_on();
            cur_led_off(); cur_led_off(); 
            cur_led_off(); cur_led_off();
            break;
        }
        // 老化测试模式----只输出RF
        case TEST_ONLY_RF_MODE:{
            cur_led_on(); cur_led_on();
            cur_led_off(); cur_led_off(); 
            cur_led_on(); cur_led_on();
            cur_led_off(); cur_led_off();
            break;
        }

        default:{
            cur_led_off(); cur_led_off();
            cur_led_off(); cur_led_off();
            cur_led_off(); cur_led_off();
            cur_led_off(); cur_led_off();
            break;
        }
    }
}

/********************************
 * 主机——所有led熄灭：
 * 正常模式下的显示
*******************************/
void close_mode_leds(void)
{
    cur_led_off(); cur_led_off();
    cur_led_off(); cur_led_off();
    cur_led_off(); cur_led_off();
    cur_led_off(); cur_led_off();
}


/********************************
 * 主机——所有led熄灭：
 * 正常模式下的显示
*******************************/
void all_led_off(void)
{
    cur_led_off();cur_led_off();
    cur_led_off();cur_led_off();
    cur_led_off();cur_led_off();
    cur_led_off();cur_led_off();  
    cur_led_off();cur_led_off();
    cur_led_off();cur_led_off();
    cur_led_off();cur_led_off();
    cur_led_off();cur_led_off();  
}

/****************************************************************
 * 主机——提示灯：1颗提示灯、5个档位灯、4颗模式灯[两颗rgb 显示一种模式]
 * 20ms调用一次
 * 
 *  rgb_index1, 状态指示灯（常亮）
 * 
 *  rgb_index2, （档位1,2）
 *  rgb_index3, （档位3,4）
 *  rgb_index4, （档位5,6）
 *  rgb_index5, （档位7,8）
 *  rgb_index6, （档位9,10）
 * 
 *  rgb_index7,rgb_index8, （模式1）
 *  rgb_index9,rgb_index10, （模式2）
 *  rgb_index11,rgb_index12, （模式3）
 *  rgb_index13,rgb_index14, （模式4）
************************************************************************/

void rgb_sip_display(void)
{
    static uint8_t last_disp_level = 0;
    static uint8_t refresh_delay_cnt = 0;
    static uint8_t force_display_delay = 0;
    static uint8_t force_display_cnt = 0;

    LEVEL_e level =0;

    switch(get_sys_state()){
        case SYS_IDLE_STA:
        case NORMAL_WORK_STA:{

        // 如果 模式--档位---颜色都相同，则直接退出，不用再刷新rgb
            if((rgb_data.disp_color == get_sys_rgb_color())&&(rgb_data.disp_mode == get_sys_mode())&&(rgb_data.disp_level == get_sys_level())){
                if(0 == get_sys_level()%2){
                    rgb_data.refresh_cnt = 24;  // 为了切回到奇数档时，立刻刷新
                    rgb_data.flicker_flag = 0;
                    last_disp_level = get_sys_level();
                }
            }
            // 当前档位为奇数时，进行闪烁
            if(get_sys_level()%2){
                rgb_data.refresh_cnt ++;

                if(rgb_data.refresh_cnt%25 == 0){
                    rgb_data.flicker_flag = ~rgb_data.flicker_flag;
                    level = get_sys_level();
                    
                    if(rgb_data.flicker_flag){
                        
                        if(last_disp_level >= level){
                        //-----如果原先档位比现在档位高，即操作了档位-，
                            level --;  
                        }
                        else{
                        //-----如果原先档位没有现在档位高，即操作了档位+，    
                            rgb_data.flicker_flag = 0;
                        }
                        
                    }
                    
                    last_disp_level = get_sys_level(); 
                    rgb_data.refresh_cnt = 0;
                }
                else{
                    return;
                }
            }
            else{
                //rgb_data.flicker_flag = 1;
                rgb_data.refresh_cnt = 24;  // 为了切回到奇数档时，立刻刷新
                level = get_sys_level();
            }

            // 如果是max 模式，并且gsensor异常
            if((sys_data.err_mode & GSENSOR_ID_ERR)&&(MAX_MODE == get_sys_mode())){
                
                if(get_sys_level()%2){
                    force_display_delay = rgb_data.refresh_cnt;
                }else{
                    force_display_delay ++;
                }

                if(force_display_delay%25 == 0){
                    if(get_sys_level()%2){
                        if(level < get_sys_level()){
                            level_leds_display(FIRST_LED_OFF, level); 
                        }
                        else{
                            level_leds_display(FIRST_LED_ON, level); 
                        }
                    }
                    else{
                        force_display_cnt ++;
                        if(force_display_cnt%2){
                            level_leds_display(FIRST_LED_ON, level); 
                        }
                        else{
                            level_leds_display(FIRST_LED_OFF, level);                           
                        }
                    }    
                    // --------------模式灯
                    mode_leds_display();
                }
                return;
            }


            // ---档位灯
            if((rgb_data.disp_level != level)||(rgb_data.disp_sta != get_sys_state())||(rgb_data.disp_color != get_sys_rgb_color())||(rgb_data.disp_mode != get_sys_mode())){
                
                level_leds_display(FIRST_LED_ON, level);
                // --------------模式灯
                mode_leds_display();
            }

            break;
        }
        /*********************
         *  老化模式： 档位灯正常亮起（同正常模式）
         *            模式灯闪烁  
         * 
        */
        case ALIGN_STA:{

            level = get_sys_level();

            rgb_data.refresh_cnt ++; 
            if(rgb_data.refresh_cnt%25 == 0){
                rgb_data.flicker_flag = ~rgb_data.flicker_flag;
            }
            else{
                return;     // 直接退出，不刷新rgb
            }

            // 当前档位为奇数时，进行闪烁
            if(get_sys_level()%2){
                // 根据闪烁flag，进行闪烁
                if(rgb_data.flicker_flag){  
                    level --;
                }
            }
            // ---档位灯
        
            // --------------模式灯
            if(rgb_data.flicker_flag){
                if(sys_data.aling_run_cnt > ALING_MODE_MAX_OUT_TIME){
                    level_leds_display(FIRST_LED_OFF, level);
                }
                else{
                    level_leds_display(FIRST_LED_ON, level);
                }
                close_mode_leds();
            }
            else{
                level_leds_display(FIRST_LED_ON, level);
                mode_leds_display();
            }
            
            break;
        }
        case ERR_STA:{
            // if(((get_sys_err_mode())& BAT_LOWEST)||((get_sys_err_mode())& BAT_LOW))
            if(rgb_data.disp_sta != ERR_STA){
                rgb_data.refresh_cnt = 0;
            }
            if(((get_sys_err_mode())& BAT_LOWEST)||(get_sys_bat_lowest_flag()))
            {       // 电池过低---闪烁提示
                rgb_data.refresh_cnt ++;
                if(rgb_data.refresh_cnt==1){
                    level = get_sys_level();
                    level_leds_display(FIRST_LED_ON, level);
                    mode_leds_display();
                }
                else if(rgb_data.refresh_cnt==25){
                    all_led_off();
                }
                if(rgb_data.refresh_cnt > 50){
                    rgb_data.refresh_cnt = 0;
                }
                
            }
            break;
        }

        case CHARGE_STA:
        case CHARGE_FINISH_STA:{
            if(rgb_data.disp_sta != get_sys_state()){
                all_led_off();
            }
            else{
                refresh_delay_cnt ++;   // 2021 10 17 防止接触不良时，显示杂色灯， 定时强制刷新
                if(refresh_delay_cnt % 10 == 0){
                    all_led_off();
                }
            }
            break;
        }

        case SLEEP_STA:{
            if(rgb_data.disp_sta != get_sys_state()){
                all_led_off();
            }
            break;
        }
        default:{

            break;
        }
    }

//    printf("rgb_level:[%d]\r\n", level);
    rgb_data.disp_sta = get_sys_state();
    rgb_data.disp_color = get_sys_rgb_color();
    rgb_data.disp_mode = get_sys_mode();
    rgb_data.disp_level = level;
    if((SLEEP_STA == get_sys_state())||(CHARGE_STA == get_sys_state())){
        rgb_data.disp_level = 0xff;
    }


}

/********
 * 暂时没有用到reset， 测试时发现将reset拉低后，led显示仍然能够保持，所以reset几乎作用
 * 
*/
void rgb_reset(void)
{
    ws2812_logic_low();
}


void my_rgb_init(void)
{
    gpio_output_cfg(SPI_MASTER_GPIO, SPI_MASTER_PIN_MOSI);
}